#include<time.h>
#include<math.h>
#include<malloc.h>
#include<stdio.h>
#include<cstdlib>
#include<fstream>
#include<iostream>
#include<sstream>

using namespace std;

#define INPUT_DIMENSION 5
#define STUDY_SPPED 0.13
#define SIZE_X 30
#define SIZE_Y 5
#define NUM_OF_NODES SIZE_Y*SIZE_X

ifstream inputFile;

typedef struct struct_node{
	double x,y;
	double activity;
	double weight[INPUT_DIMENSION];
}node;

int getInput(double* one_input)
{
	string line;
	if (getline(inputFile,line))
	{
		istringstream iss(line);
		int i=0;
		do
		{
			string sub;
			iss >>sub;
			one_input[i++]=atof(sub.c_str());
		} while (iss);
		return 1;
	}
	else return 0;
}

double getDistance(double * weight,double * input_vector)
{
	double sum=0;
	for (int i=0;i<INPUT_DIMENSION;i++)
	{
		sum+=(weight[i]-input_vector[i])*(weight[i]-input_vector[i]);
	}
	return sum;
}

double theta(double distance)
{
	if (distance<0.0000001) return 2;
	else return 1/distance;
}

int printNodes(node * nodes,int BFU,double* distances)
{
	for (int i=0;i<NUM_OF_NODES;i++)
	{
		if (BFU==i) printf("\033[31;49;1m"); 
		if (BFU==i) printf("["); else printf(" ");
		for (int q=0;q<INPUT_DIMENSION;q++)
		{
			printf("%.2f ",nodes[i].weight[q]);
		}
		if (BFU==i) printf("\033[39;49;0m"); 
		if (BFU==i) printf("]"); else printf(" ");
		printf("(%.1f)",distances[i]);
		printf(" ");
		if (i%SIZE_Y==SIZE_Y-1) printf("\n");
	}
	printf("\n");
}

int main()
{
	inputFile.open("input");
	string line;
	srand( (unsigned)time( NULL ));

	node* nodes;
	nodes=(node *)malloc(NUM_OF_NODES*sizeof(node));

	printf("som tester\n----------------------\ninit weighs:\n");

	/*init nodes*/
	for (int i=0;i<NUM_OF_NODES;i++)
	{
		node n;
		n.x=i/SIZE_Y;
		n.y=i%SIZE_Y;
		n.activity=0;

		for (int j=0;j<INPUT_DIMENSION;j++)
		{
			n.weight[j]=(double)(rand()%10000)/(double)10000;
		}
		nodes[i]=n;
	}

	double one_input[INPUT_DIMENSION];
	int counter = 0;
	while (getInput(one_input))
	{
		printf("input: %f %f %f %f %f\n",one_input[0],one_input[1],one_input[2],one_input[3],one_input[4]);	
		/*step1 find the BFU(Best Fired Unit)*/
		int BFU=0;
		double min_distance=10000;
		for (int i=0;i<NUM_OF_NODES;i++)	
		{
			if (min_distance>getDistance(nodes[i].weight,one_input))
			{
				min_distance=getDistance(nodes[i].weight,one_input);
				BFU=i;
			}
		}
		cout<<"BFU:"<<BFU<<endl;

		double distances[NUM_OF_NODES];

		/*step2 change weight*/
		for (int i=0;i<NUM_OF_NODES;i++)	
		{
			for (int j=0;j<INPUT_DIMENSION;j++)
			{
				distances[i]=theta(pow(nodes[i].x-nodes[BFU].x,2)+pow(nodes[i].y-nodes[BFU].y,2));
				//distances[i]=(1-(fabs(nodes[i].x-nodes[BFU].x))+fabs(nodes[i].y-nodes[BFU].y))/(NUM_OF_NODES*2);
				nodes[i].weight[j]=nodes[i].weight[j]+distances[i]*STUDY_SPPED*(one_input[j]-nodes[i].weight[j]);
			}
		}

		if (counter % 20 == 0)
		{
			printNodes(nodes,BFU,distances);
			sleep(1);
		}
		counter ++;
	}

	inputFile.close();
	return 0;
}


